#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

#define PORCESS_NUM 5
#define TASK_NUM 3
#define TASK_COUNT 10
#define Initsrand() srand((unsigned int)time(nullptr) | getpid())

typedef void(*func_t) (); //注意函数指针的写法 返回值(*)(参数类型)!!!;

func_t task_table[TASK_NUM];

void func1(){
    std::cout<<"-->下载任务"<<std::endl;;
    sleep(1);
}
void func2(){
    std::cout<<"-->安装任务"<<std::endl;;
    sleep(1);
}
void func3(){
    std::cout<<"-->启动任务"<<std::endl;;
    sleep(1);
}

void load_task(){
    task_table[0] = func1;
    task_table[1] = func2;
    task_table[2] = func3;
}


class process_info{
public:
    process_info(pid_t pid,int wfd)
        :_pid(pid),_wfd(wfd)
    {
        char buffer[1024];
        sprintf(buffer,"process[pid:%d][wfd:%d][cnt:%d]",_pid,_wfd,cnt++);
        _name = buffer;
    }
public:
    std::string _name;
    static int cnt ;
    pid_t _pid;
    int _wfd;
};
int process_info::cnt = 0;

void Createporeccss(std::vector<process_info>& info_table,std::vector<int>& deletefd){
    for (int i = 0; i < PORCESS_NUM; i++){
        // 父进程打开匿名管道
        int fds[2];
        int r = pipe(fds);
        assert(r == 0);
        (void)r;
        // 子进程fork后继承匿名管道
        pid_t id = fork();
        if (id == 0){
            for(const auto& x : deletefd)   close(x);
            // 进入子进程逻辑（接受任务，并完成任务）
            close(fds[1]);
            while(true){
                //接受任务码
                int Command_Code;
                ssize_t r = read(fds[0],&Command_Code,sizeof(int));
                //执行任务
                if(r == 0) break;
                task_table[Command_Code] ();
            }
            
            exit(0);
        }
        close(fds[0]);
        deletefd.push_back(fds[1]);
        info_table.push_back(process_info(id,fds[1]));
    }
}

void wait_childprocess(std::vector<process_info>& info_table){
    for (size_t i = 0; i < PORCESS_NUM; i++){
        waitpid(info_table[i]._pid,NULL,0);
        std::cout<<"on sucess exit :" << info_table[i]._pid<<std::endl;
    }
    
}

void Send_task(std::vector<process_info>& info_table){
    int cout = TASK_COUNT;

    while(cout--){
        int index_process = rand()%PORCESS_NUM;
        int index_task = rand()%TASK_NUM;
        std::cout<<info_table[index_process]._name<<std::endl;
        ssize_t s = write(info_table[index_process]._wfd,&index_task,sizeof(int));
        sleep(1);
        assert(s == 4);
    }
    //关闭写端，读端就会读完后读到0;
    for(int i = 0 ; i < PORCESS_NUM ; i++) close(info_table[i]._wfd);
}


int main(){
    std::vector<int> deletefd;
    //
    std::vector<process_info> info_table;
    load_task();
    // 循环创建指定个数的子进程，打开信道，并保存信息
    Createporeccss(info_table,deletefd);
    Initsrand();
    //父进程逻辑:发送Commnade Code
    Send_task(info_table);
    //等待子进程
    wait_childprocess(info_table);

    return 0;
}